/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

/*******************************************************************************
 * DWT: DWT port for the D Language
 * 
 * Contributors: The DWT team at http://www.dsource.org/projects/dwt
 *  
 ******************************************************************************/


module dwt.util.util;

private 
{
	import dwt.dwt;
	import dwt.internal.win32.os;
	import tango.sys.win32.IUnknown;
}


int foo = 0;


template MathT(T)
{
	public static T abs(T x) {
		return x > 0 ? x : -x;
	}

	public static T min(T a, T b) {
		return a >= b ? b : a;
	}

	public static T max(T a, T b) {
		return a >= b ? a : b;
	}
}


public class Util {

	/++
	static void trace(Object obj, boolean appendCRLF = true){
		debug{
			if(obj !is null) trace(obj.toString(), appendCRLF);
			else trace("null", appendCRLF);
		}
	}
	
	private static void _trace(char[] s, boolean appendCRLF = true)
	{
		debug{
			if(s is null) {
				_trace("null\n", false);
				return;
			}
			char[] cs = appendCRLF ? s ~ "\n" : s;
			std.stdio.printf(Converter.StrToMBCSz(cs));		
			OS.OutputDebugString(Converter.StrToTCHARz(cs));
		}
	}
	++/
	
	static void trace(T...)(T t)
	{
		debug{
			
			/++
				void putc(dchar c)
				{
					std.utf.encode(s, c);
				}
				try{
					std.format.doFormat(&putc, _arguments, _argptr);
					_trace(s);
				}catch(Object o){
					// do nothing
				}
			++/
	    }
	}

	
	public static void printObj(Object obj, char[] name = null){
		debug{
			if(name)
				trace(name ~ "'s Address = " ~ Int.toString(cast(uint)cast(void*)obj));
			else
				trace("Address = " ~   Int.toString(cast(uint)cast(void*)obj));
		}
	}
	

	public static char[] getExePathName(int hInst = 0, boolean pathOnly = false){
		TCHAR[] buffer = new TCHAR[OS.MAX_PATH * 2];
		int cch = OS.GetModuleFileName(cast(HANDLE)hInst, buffer.ptr, buffer.length);
		char[] exepath = Converter.TCHARzToStr(buffer.ptr, cch);
		if(pathOnly){
			int  i;
			for(i = exepath.length -1 ; i >=0 ; i -- ){
				if( exepath[i] is '/' || exepath[i] is '\\' ){
					break;
				}
			}
			return exepath[ 0 .. i ];
		}
		return exepath;
	}

/*	
deprecated {
	alias MathT!(int).abs abs;
	alias MathT!(byte).abs abs;
	alias MathT!(double).abs abs;
	alias MathT!(float).abs abs;
	alias MathT!(short).abs abs;
	alias MathT!(long).abs abs;

	alias MathT!(int).min min;
	alias MathT!(byte).min min;
	alias MathT!(double).min min;
	alias MathT!(float).min min;
	alias MathT!(short).min min;
	alias MathT!(long).min min;
	alias MathT!(uint).min min;
	alias MathT!(ushort).min min;
	alias MathT!(ubyte).min min;
	alias MathT!(ulong).min min;

	alias MathT!(int).max max;
	alias MathT!(byte).max max;
	alias MathT!(double).max max;
	alias MathT!(float).max max;
	alias MathT!(short).max max;
	alias MathT!(long).max max;
	alias MathT!(uint).max max;
	alias MathT!(ushort).max max;
	alias MathT!(ubyte).max max;
	alias MathT!(ulong).max max;	
}
*/
}

class Math 
{
	alias MathT!(int).abs abs;
	alias MathT!(byte).abs abs;
	alias MathT!(double).abs abs;
	alias MathT!(float).abs abs;
	alias MathT!(short).abs abs;
	alias MathT!(long).abs abs;

	alias MathT!(int).min min;
	alias MathT!(byte).min min;
	alias MathT!(double).min min;
	alias MathT!(float).min min;
	alias MathT!(short).min min;
	alias MathT!(long).min min;
	alias MathT!(uint).min min;
	alias MathT!(ushort).min min;
	alias MathT!(ubyte).min min;
	alias MathT!(ulong).min min;

	alias MathT!(int).max max;
	alias MathT!(byte).max max;
	alias MathT!(double).max max;
	alias MathT!(float).max max;
	alias MathT!(short).max max;
	alias MathT!(long).max max;
	alias MathT!(uint).max max;
	alias MathT!(ushort).max max;
	alias MathT!(ubyte).max max;
	alias MathT!(ulong).max max;
}

deprecated alias SimpleType SimpType;

template SimpleType(T)
{
	debug{
		static void validCheck(uint SrcLen, uint DestLen, uint copyLen){
			if(SrcLen < copyLen || DestLen < copyLen|| SrcLen < 0 || DestLen < 0){
				Util.trace("Error : SimpleType.arraycopy(), out of bounds.");
				assert(0);
			}
		}
	}
	 
	
	static void remove(inout T[] items, int index)
	{
		if(items.length == 0)
			return;
		
		if(index < 0 || index >= items.length){
			DWT.error(__FILE__, __LINE__, "Out of array bounds.");
			return;
		}
		
		T element = items[index];
		
		int length = items.length;
		if(length == 1){				
			items.length = 0;
			return;// element;
		}
		
		if(index == 0)
			items = items[1 .. $];
		else if(index == length - 1)
			items = items[0 .. index];
		else
			items = items[0 .. index] ~ items[index + 1 .. $];
	}
	
//	static void remove(inout T[] items, T item)
//	{
//		if(items.length == 0 ) 
//			return;
//			
//		
//		for(int i = 0; i < items.length; i++){
//			if(item == items[i]){
//				remove(items, i);
//				return;
//			}
//		}
//	}
	
	static void insert(inout T[] items, T item, int index = -1)
	{	
		if(index == -1)
			index = items.length;
		
		if(index < 0 || index > items.length ){
			DWT.error(__FILE__, __LINE__, "Out of array bounds.");
			return;
		}
			
		if(index == items.length){
			items ~= item;
		}else if(index == 0){
			T[] newVect;
			newVect ~= item;
			items = newVect ~ items;
		}else if(index < items.length ){
			T[] arr1 = items[0 .. index];
			T[] arr2 = items[index .. $];

			// Important : if you write like the following commented, 
			// you get wrong data
			// code:  T[] arr1 = items[0..index];
			//        T[] arr2 = items[index..$];
			//        items = arr1 ~ item;		// error, !!!
			//        items ~= arr2;			// item replace the arrr2[0] here
			items = arr1 ~ item ~ arr2;
		}
	}
	
	static void arraycopy(T[] src, uint srcPos, T[] dest, uint destPos, uint len)
	{
		if(len == 0) return; 

		assert(src); 
		assert(dest);
		debug{validCheck(src.length - srcPos, dest.length - destPos, len);}
		
		if(src is dest){
			for(int i=0; i<len; ++i){
				dest[destPos+i] = src[srcPos+i];
			}
		}else{
			dest[destPos..(len+destPos)] = src[srcPos..(len+srcPos)];
		}	
	}	
}

	 
extern(Windows) int GetTickCount();
	
class System
{
	// import GUID
	
	public static long currentTimeMillis(){
		return GetTickCount();
	}
	alias SimpleType!(int).arraycopy arraycopy;
	alias SimpleType!(byte).arraycopy arraycopy;
	alias SimpleType!(double).arraycopy arraycopy;
	alias SimpleType!(float).arraycopy arraycopy;
	alias SimpleType!(short).arraycopy arraycopy;
	alias SimpleType!(long).arraycopy arraycopy;
	alias SimpleType!(uint).arraycopy arraycopy;
	alias SimpleType!(ushort).arraycopy arraycopy;
	alias SimpleType!(ubyte).arraycopy arraycopy;
	alias SimpleType!(ulong).arraycopy arraycopy;	
	alias SimpleType!(char).arraycopy arraycopy;	
	alias SimpleType!(wchar).arraycopy arraycopy;	
	alias SimpleType!(Object).arraycopy arraycopy;
	alias SimpleType!(void*).arraycopy arraycopy;
	alias SimpleType!(HANDLE).arraycopy arraycopy;
	alias SimpleType!(IUnknown).arraycopy arraycopy;
	alias SimpleType!(GUID*).arraycopy arraycopy;


	alias SimpleType!(int[]).arraycopy arraycopy;
	alias SimpleType!(byte[]).arraycopy arraycopy;
	alias SimpleType!(double[]).arraycopy arraycopy;
	alias SimpleType!(float[]).arraycopy arraycopy;
	alias SimpleType!(short[]).arraycopy arraycopy;
	alias SimpleType!(long[]).arraycopy arraycopy;
	alias SimpleType!(uint[]).arraycopy arraycopy;
	alias SimpleType!(ushort[]).arraycopy arraycopy;
	alias SimpleType!(ubyte[]).arraycopy arraycopy;
	alias SimpleType!(ulong[]).arraycopy arraycopy;	
	alias SimpleType!(char[]).arraycopy arraycopy;	
	alias SimpleType!(wchar[]).arraycopy arraycopy;	
	alias SimpleType!(Object[]).arraycopy arraycopy;
	alias SimpleType!(LPVOID[]).arraycopy arraycopy;
	alias SimpleType!(HANDLE[]).arraycopy arraycopy;
	alias SimpleType!(IUnknown[]).arraycopy arraycopy;
	alias SimpleType!(GUID*[]).arraycopy arraycopy;

}

  
